]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
StThemeNodeDrawing: clear out node interior before filling pattern
authorRay Strode <rstrode@redhat.com>
Tue, 15 Feb 2011 22:04:30 +0000 (17:04 -0500)
committerRay Strode <rstrode@redhat.com>
Wed, 16 Feb 2011 00:57:52 +0000 (19:57 -0500)
If we aren't going to fill the content area of the node with a solid
background color, then we need to clear it of any artifacts left over
from drawing the border.

https://bugzilla.gnome.org/show_bug.cgi?id=640465

src/st/st-theme-node-drawing.c

index 088ab483a0cbb9f3dfbb95afb35d4596caa8c23f..e9e12b7b2954a2e85b42d399c8174cc49b446c7e 100644 (file)
@@ -725,6 +725,8 @@ st_theme_node_render_background_with_border (StThemeNode *node)
   cairo_pattern_t *pattern = NULL;
   cairo_path_t *outline_path = NULL;
   gboolean draw_solid_background = TRUE;
+  gboolean background_is_translucent;
+  gboolean interior_dirty;
   gboolean draw_background_image_shadow = FALSE;
   gboolean has_visible_outline;
   ClutterColor border_color;
@@ -765,6 +767,12 @@ st_theme_node_render_background_with_border (StThemeNode *node)
   rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
                                              paint_box.x2 - paint_box.x1);
   data = g_new0 (guchar, (paint_box.y2 - paint_box.y1) * rowstride);
+
+  /* We zero initialize the destination memory, so it's fully transparent
+   * by default.
+   */
+  interior_dirty = FALSE;
+
   surface = cairo_image_surface_create_for_data (data,
                                                  CAIRO_FORMAT_ARGB32,
                                                  paint_box.x2 - paint_box.x1,
@@ -789,6 +797,17 @@ st_theme_node_render_background_with_border (StThemeNode *node)
     {
       pattern = create_cairo_pattern_of_background_gradient (node);
       draw_solid_background = FALSE;
+
+      /* If the gradient has any translucent areas, we need to
+       * erase the interior region before drawing, so that we show
+       * what's actually under the gradient and not whatever is
+       * left over from filling the border, etc.
+       */
+      if (node->background_color.alpha < 255 ||
+          node->background_gradient_end.alpha < 255)
+        background_is_translucent = TRUE;
+      else
+        background_is_translucent = FALSE;
     }
   else
     {
@@ -803,11 +822,25 @@ st_theme_node_render_background_with_border (StThemeNode *node)
           if (shadow_spec && pattern != NULL)
             draw_background_image_shadow = TRUE;
         }
+
+      /* We never need to clear the interior region before drawing the
+       * background image, because it either always fills the entire area
+       * opaquely, or we draw the solid background behind it.
+       */
+      background_is_translucent = FALSE;
     }
 
   if (pattern == NULL)
     draw_solid_background = TRUE;
 
+  /* drawing the solid background implicitly clears the interior
+   * region, so if we're going to draw a solid background before drawing
+   * the background pattern, then we don't need to bother also clearing the
+   * background region.
+   */
+  if (draw_solid_background)
+    background_is_translucent = FALSE;
+
   has_visible_outline = st_theme_node_has_visible_outline (node);
 
   /* Create a path for the background's outline first */
@@ -858,6 +891,11 @@ st_theme_node_render_background_with_border (StThemeNode *node)
                              border_color.alpha / 255.);
       cairo_fill (cr);
 
+      /* We were sloppy when filling in the border, and now the interior
+       * is filled with the border color, too.
+       */
+      interior_dirty = TRUE;
+
       if (radius[ST_CORNER_TOPLEFT] > MAX(border_width[ST_SIDE_TOP],
                                           border_width[ST_SIDE_LEFT]))
         elliptical_arc (cr,
@@ -937,6 +975,13 @@ st_theme_node_render_background_with_border (StThemeNode *node)
       cairo_append_path (cr, outline_path);
     }
 
+  if (interior_dirty && background_is_translucent)
+    {
+      cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+      cairo_fill_preserve (cr);
+      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+    }
+
   if (draw_solid_background)
     {
       cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);